package yby

import (
	"fmt"
	"gitee.com/hongzhaomin/hzm-common-go/beautify"
	"gitee.com/hongzhaomin/hzm-common-go/easycmd"
	"gitee.com/hongzhaomin/hzm-common-go/streams"
	"github.com/hirochachacha/go-smb2"
	"io"
	"io/fs"
	"net"
	"path"
	"path/filepath"
	"strings"
)

var _ easycmd.Handler = (*CopyFile)(nil)

type CopyFile struct {
	No           string `json:"no,omitempty" argName:"no" usage:"搜索编号，多个请用英文逗号连接"`
	WantDir      string `json:"wantDir,omitempty" argName:"wantDir" usage:"想要的目录" initVal:"唯品"`
	UserName     string `json:"userName,omitempty" argName:"user" usage:"用户名" initVal:"菜花"`
	Password     string `json:"password,omitempty" argName:"pwd" usage:"密码" initVal:"ch123123"`
	ServerName   string `json:"serverName,omitempty" argName:"serv" usage:"服务名" initVal:"192.168.1.109"`
	SourcePath   string `json:"sourcePath,omitempty" argName:"src" usage:"源路径" initVal:"商品\\商品详情\\2025夏上新"`
	TargetPath   string `json:"targetPath,omitempty" argName:"dest" usage:"目标路径" initVal:"私域\\每日文案"`
	NewTargetDir string `json:"newTargetDir,omitempty" argName:"ndir" usage:"需要创建的文件夹"`

	noList      []string
	sourceShare string
	targetShare string
}

func (my *CopyFile) convertData() {
	if strings.HasPrefix(my.SourcePath, `\`) {
		my.SourcePath = my.SourcePath[1:]
	}
	if strings.HasPrefix(my.TargetPath, `\`) {
		my.TargetPath = my.TargetPath[1:]
	}

	my.noList = streams.OfSlice(strings.Split(my.No, ",")).
		MapToString(func(s string) string {
			return strings.Trim(s, " ")
		}).ToSlice()

	my.sourceShare = strings.Split(my.SourcePath, string(filepath.Separator))[0] // 商品
	my.targetShare = strings.Split(my.TargetPath, string(filepath.Separator))[0] // 私域

	//fmt.Println(beautify.FmtJson(my))
}

func (my *CopyFile) DoHandle(_ *easycmd.Command) {
	if my.No == "" {
		fmt.Println(">>> 请输入编号参数，例如：-no=1234")
		return
	}
	if my.NewTargetDir == "" {
		fmt.Println(">>> 请输入需要创建的文件夹，例如：-ndir=imgtest")
		return
	}
	my.convertData()

	// smb连接
	conn, err := net.Dial("tcp", my.ServerName+":445")
	if err != nil {
		fmt.Println(fmt.Sprintf("共享盘[%s]连接异常：%v", my.ServerName, err))
		return
	}
	defer conn.Close()

	d := &smb2.Dialer{
		Initiator: &smb2.NTLMInitiator{
			User:     my.UserName,
			Password: my.Password,
		},
	}
	s, err := d.Dial(conn)
	if err != nil {
		fmt.Println(fmt.Sprintf("共享盘登录失败，user: %s, pwd: %s：%v", my.UserName, my.Password, err))
		return
	}
	defer s.Logoff()

	srcShare, err := s.Mount(my.sourceShare)
	if err != nil {
		fmt.Println(fmt.Sprintf("挂载源共享盘目录异常：%v", err))
		return
	}
	defer srcShare.Umount()

	destShare, err := s.Mount(my.targetShare)
	if err != nil {
		fmt.Println(fmt.Sprintf("挂载目标共享盘目录异常：%v", err))
		return
	}
	defer destShare.Umount()

	// 递归扫描共享目录
	var results []SearchResult
	var total int
	rootPath := `.` + strings.ReplaceAll(my.SourcePath[len(my.sourceShare):], `\`, `/`)                                // ./商品详情/2025夏上新
	dstRootPath := `.` + path.Join(strings.ReplaceAll(my.TargetPath[len(my.targetShare):], `\`, `/`), my.NewTargetDir) // ./每日文案/newDir
	err = fs.WalkDir(srcShare.DirFS("."), rootPath, func(fPath string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		if fPath == rootPath {
			return nil
		}

		if d.IsDir() {
			return nil
		}

		currentNo := ""
		if streams.OfSlice(my.noList).AnyMatch(func(no string) bool {
			contains := strings.Contains(fPath, no)
			if contains {
				currentNo = no
			}
			return contains
		}) {
			// fPath 包含，说明进入符合条件的目录下面了
			// 那么这里面所有的文件及其文件夹都需要拷贝
			if !d.IsDir() {
				dir, copyFile := path.Split(fPath)
				_, pDir := path.Split(dir[:len(dir)-1])  // 当前文件的文件夹
				if !strings.Contains(pDir, my.WantDir) { // 只提取想要文件夹下的文件，其他的不要
					return nil
				}
				// 文件
				// 拷贝到目标路径
				dstParentDir := currentNo + "-" + pDir
				destPath := path.Join(dstRootPath, dstParentDir, copyFile)
				if strings.HasPrefix(destPath, `./`) {
					destPath = destPath[len(`./`):]
				}
				destDir, _ := path.Split(destPath)
				if err = destShare.MkdirAll(destDir, 0666); err != nil {
					fmt.Println(fmt.Sprintf("创建目标文件夹[%s]失败：%v", destDir, err))
					return nil
				}
				destFile, err2 := destShare.Create(destPath)
				if err2 != nil {
					fmt.Println(fmt.Sprintf("创建目标文件[%s]失败：%v", destPath, err2))
					return nil
				}

				srcPath := fPath
				if strings.HasPrefix(srcPath, `./`) {
					srcPath = srcPath[len(`./`):]
				}
				fmt.Println(fmt.Sprintf(">>> 找到需要拷贝的文件：%s", srcPath))
				srcFile, err3 := srcShare.Open(srcPath)
				if err3 != nil {
					fmt.Println(fmt.Sprintf("打开源文件[%s]失败：%v", srcPath, err3))
					return nil
				}
				_, err = io.Copy(destFile, srcFile) // 返回拷贝字节数‌:ml-citation{ref="1,3" data="citationList"}
				if err != nil {
					fmt.Println(fmt.Sprintf("拷贝源文件[%s]失败：%v", srcPath, err))
					return nil
				}

				// 统计成功数据
				total++
				fullSrc := strings.ReplaceAll(filepath.Join(my.ServerName, my.sourceShare, fPath), `/`, `\`)
				fullDst := strings.ReplaceAll(filepath.Join(my.ServerName, my.targetShare, destPath), `/`, `\`)
				results = append(results, SearchResult{
					No:         total,
					SourceFile: fullSrc,
					TargetFile: fullDst,
				})
			}
		}
		return nil
	})

	if err != nil {
		fmt.Println(fmt.Sprintf("文件扫描异常：%v", err))
		return
	}

	fmt.Println(fmt.Sprintf(">>> 照片搜索完成，拷贝成功 %d 个文件", len(results)))
	if len(results) > 0 {
		beautify.TabPrint4Struct(results)
		p := strings.ReplaceAll(dstRootPath, `/`, `\`)
		fmt.Println(fmt.Sprintf(">>> 去查看拷贝文件，目录地址：%s",
			filepath.Join(`\\`, my.ServerName, p[len(`./`):])))
	}

}

type SearchResult struct {
	No         int    `json:"No,omitempty" title:"序号"`               // 序号
	SourceFile string `json:"SourceFile,omitempty" title:"找到的文件地址"`  // 找到的文件
	TargetFile string `json:"TargetFile,omitempty" title:"拷贝完的文件地址"` // 拷贝完的文件
}
